package Database;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;


public class TripleDES {

	public  SecretKey _key;
	private Cipher decipher;
	private Cipher encipher;
	private byte[] key_bytes;

/**
 * Constructor
 * @param keyString the key for the triple des algorithem
 */
	public TripleDES(String keyString) {
		byte[] keyB = new byte[24]; // a Triple DES key is a byte[24] array

		for (int i = 0; i < keyString.length() && i < keyB.length; i++) {
			keyB[i] = (byte) keyString.charAt(i);
		}
		// Make the Key
		_key = new SecretKeySpec(keyB, "DESede");

		try {
			decipher = Cipher.getInstance("DESede");
			decipher.init(Cipher.DECRYPT_MODE, _key);

		} catch (javax.crypto.NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (java.security.NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (java.security.InvalidKeyException e) {
			e.printStackTrace();
		}
		try {
			encipher = Cipher.getInstance("DESede");
			encipher.init(Cipher.ENCRYPT_MODE, _key);
			key_bytes = _key.getEncoded();
		} catch (javax.crypto.NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (java.security.NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (java.security.InvalidKeyException e) {
			e.printStackTrace();
		}
	}

	/**
	 * gets a key and a key, and encryptes the string with the key in triple-des
	 * @param key the key
	 * @param string the string to encrypt
	 * @return the newly encrypted string
	 */
	public  String encryptString(SecretKey key, String string) {
		return encrypt(string);
	}

	/**
	 * @param key the key
	 * @param string the string to decrypt
	 * @return the decrypted string
	 */
	public  String decryptString(SecretKey key, String string) {
		return decrypt(string);
	}

	/**
	 * takes a name of file with data, and encrypt the data to the output file.
	 * @param file_to_encrypt
	 * @param output_file
	 */
	public  void encrypt_file(String file_to_encrypt, String output_file) {
		try {
			//input file
			File input_file = new File(file_to_encrypt);
			FileInputStream fis = null;
			BufferedReader bis = null;
			fis = new FileInputStream(input_file);
			bis = new BufferedReader(new InputStreamReader(fis));


			//output file for list
			FileWriter fstream = new FileWriter(output_file);
			BufferedWriter out = new BufferedWriter(fstream);


			//writing to the file....
			String line = null;
			line = bis.readLine();
			if (line != null)
				out.write(encryptString(_key, line));

			while ((line = bis.readLine()) != null) {
				out.write("\n" + encryptString(_key,line));
			}


			// dispose all the resources after using them.
			fis.close();
			bis.close();
			out.close();
			fstream.close();

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	

	/**
	 * takes a string and decrypt it with the key.
	 * @param str
	 * @return the decrypted string
	 */
	public String decrypt(String str) {
		try {
			byte[] decipher1 = new sun.misc.BASE64Decoder().decodeBuffer(str);

			byte[] decryptedBytes = decipher.doFinal(decipher1);

			return new String(decryptedBytes, "UTF8");
		} catch (javax.crypto.BadPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (java.io.IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * gets a string and encrypt it
	 * @param str
	 * @return the new encrypted string
	 */
	public String encrypt(String str) {
		try {
			byte[] encipher1 = str.getBytes("UTF8");
			byte[] encrpyedBytes = encipher.doFinal(encipher1);
			return (new sun.misc.BASE64Encoder().encode(encrpyedBytes));

		} catch (javax.crypto.BadPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}


}